/*
 * 20201103 修改自github项目 Vue-DragDrag
 */
import { dom } from 'quasar'

const { height, width } = dom

export default {
  name: 'drag',
  mounted: (el, binding) => {
    if (binding.value === false) {
      el.style.cursor = binding.value && binding.value.cursor ? binding.value.cursor : 'default'
      return
    }
    // 拖拽时的手势
    el.style.cursor = binding.value && binding.value.cursor ? binding.value.cursor : 'move'
    // 取传入元素的父元素为拖动元素
    const moveEl = el.parentNode
    // 为拖动元素添加绝对定位
    moveEl.style.position = 'absolute'
    if (!binding.oldValue && binding.value) {
      if (moveEl.style.top === '0px') {
        moveEl.style.top = `calc(50% - ${height(moveEl) / 2}px)`
      }
      if (moveEl.style.left === '0px') {
        moveEl.style.left = `calc(50% - ${width(moveEl) / 2}px)`
      }
    }
    // 如果容器为设置position属性，默认为 position = 'relative'
    if (getComputedStyle(moveEl.parentNode, null).position === 'static') {
      moveEl.parentNode.style.position = 'relative'
    }
    const mouseDownFn = e => {
      // .shaow---------- 复制节点，并且插入容器中原来位置
      let newNode = null
      if (binding.modifiers.shaow) {
        newNode = moveEl.cloneNode(true)
        moveEl.style.opacity = '0.5'
        moveEl.parentNode.appendChild(newNode)
      }
      let disX, disY
      if (!binding.modifiers.dragY) disX = (e.touches ? e.touches[0].clientX : e.clientX) - moveEl.offsetLeft
      if (!binding.modifiers.dragX) disY = (e.touches ? e.touches[0].clientY : e.clientY) - moveEl.offsetTop
      const mouseMoveFn = e => {
        if (!e.touches) e.preventDefault()
        let left = (e.touches ? e.touches[0].clientX : e.clientX) - disX
        let top = (e.touches ? e.touches[0].clientY : e.clientY) - disY
        // 可以拖出去的元素的剩余宽度
        // dragOutX
        const limitWidth = binding.value && binding.value.dragOutX ? moveEl.offsetWidth - binding.value.dragOutX : 0
        // dragOutY
        let limitHeight = 0
        let limitHeightTop = 0
        if (binding.value && binding.value.dragOutY) {
          limitHeight = moveEl.offsetHeight - binding.value.dragOutY
          // 防止可拖拽区域被拖出容器区域
          // 拖拽元素在顶部
          limitHeightTop = el.offsetHeight - binding.value.dragOutY
        }
        if (left < 0 - limitWidth) left = 0 - limitWidth
        else if (left > moveEl.parentNode.clientWidth - moveEl.offsetWidth + limitWidth) {
          left = moveEl.parentNode.clientWidth - moveEl.offsetWidth + limitWidth
        }
        if (top < 0 - limitHeightTop) top = 0 - limitHeightTop
        else if (top > moveEl.parentNode.clientHeight - moveEl.offsetHeight + limitHeight) {
          top = moveEl.parentNode.clientHeight - moveEl.offsetHeight + limitHeight
        }
        moveEl.style.left = left + 'px'
        moveEl.style.top = top + 'px'
        // 拖拽事件
        if (binding.value && binding.value.ondrag) {
          if (typeof binding.value.ondrag !== 'function') return // throw 'ondrag: should be a function'
          binding.value.ondrag(e, { left, top })
        }
      }
      // mousemove
      if (e.touches) document.addEventListener('touchmove', mouseMoveFn)
      else document.addEventListener('mousemove', mouseMoveFn)
      const mouseUpFn = function () {
        // 移除临时shaow节点
        if (newNode) {
          moveEl.style.opacity = '1'
          newNode.parentNode.removeChild(newNode)
        }
        document.removeEventListener('touchend', mouseUpFn)
        document.removeEventListener('touchmove', mouseMoveFn)
        document.removeEventListener('mousemove', mouseMoveFn)
        document.removeEventListener('mouseup', mouseUpFn)
      }
      //  mouseup
      if (e.touches) document.addEventListener('touchend', mouseUpFn)
      else document.addEventListener('mouseup', mouseUpFn)
    }
    el.__hoverDelayHandlers = { mouseDownFn }
    // mousedown
    el.addEventListener('touchstart', mouseDownFn)
    el.addEventListener('mousedown', mouseDownFn)
  },
  beforeUnmount: el => {
    const handlers = el.__hoverDelayHandlers
    if (handlers) {
      const { mouseDownFn } = handlers
      el.removeEventListener('touchstart', mouseDownFn)
      el.removeEventListener('mousedown', mouseDownFn)
      delete el.__hoverDelayHandlers
    }
  }
}